package config;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import java.io.InputStream;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Properties;
import javax.cache.configuration.Factory;
import javax.sql.DataSource;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.cache.QueryIndexType;
import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
import org.apache.ignite.cache.store.jdbc.JdbcType;
import org.apache.ignite.cache.store.jdbc.JdbcTypeField;
import org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;

/** This file was generated by Ignite Web Console (11/01/2019, 14:17) **/
public class ClientConfigurationFactory {
    /** Secret properties loading. **/
    private static final Properties props = new Properties();

    static {
        try (InputStream in = IgniteConfiguration.class.getClassLoader().getResourceAsStream("secret.properties")) {
            props.load(in);
        }
        catch (Exception ignored) {
            // No-op.
        }
    }

    /** Helper class for datasource creation. **/
    public static class DataSources {
        public static final MysqlDataSource INSTANCE_dsMySQL_Shipnettestv3 = createdsMySQL_Shipnettestv3();

        private static MysqlDataSource createdsMySQL_Shipnettestv3() {
            MysqlDataSource dsMySQL_Shipnettestv3 = new MysqlDataSource();

            dsMySQL_Shipnettestv3.setURL(props.getProperty("dsMySQL_Shipnettestv3.jdbc.url"));
            dsMySQL_Shipnettestv3.setUser(props.getProperty("dsMySQL_Shipnettestv3.jdbc.username"));
            dsMySQL_Shipnettestv3.setPassword(props.getProperty("dsMySQL_Shipnettestv3.jdbc.password"));

            return dsMySQL_Shipnettestv3;
        }
    }

    /**
     * Configure grid.
     * 
     * @return Ignite configuration.
     * @throws Exception If failed to construct Ignite configuration instance.
     **/
    public static IgniteConfiguration createConfiguration() throws Exception {
        IgniteConfiguration cfg = new IgniteConfiguration();

        cfg.setClientMode(true);
        cfg.setIgniteInstanceName("Ship");

        TcpDiscoverySpi discovery = new TcpDiscoverySpi();

        TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();

        ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47510"));

        discovery.setIpFinder(ipFinder);

        cfg.setDiscoverySpi(discovery);

        cfg.setCacheConfiguration(
            cacheShipCache(),
            cacheShipGovernorCache(),
            cacheShipGovernorLinkCache(),
            cacheShipOwnerCache()
        );

        return cfg;
    }

    /**
     * Create configuration for cache "ShipCache".
     * 
     * @return Configured cache.
     * @throws Exception if failed to create cache configuration.
     **/
    public static CacheConfiguration cacheShipCache() throws Exception {
        CacheConfiguration ccfg = new CacheConfiguration();

        ccfg.setName("ShipCache");
        ccfg.setCacheMode(CacheMode.PARTITIONED);
        ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
        ccfg.setCopyOnRead(true);

        CacheJdbcPojoStoreFactory cacheStoreFactory = new CacheJdbcPojoStoreFactory();

        cacheStoreFactory.setDataSourceFactory(new Factory<DataSource>() {
            /** {@inheritDoc} **/
            @Override public DataSource create() {
                return DataSources.INSTANCE_dsMySQL_Shipnettestv3;
            };
        });

        cacheStoreFactory.setDialect(new MySQLDialect());

        cacheStoreFactory.setTypes(jdbcTypeShip(ccfg.getName()));

        ccfg.setCacheStoreFactory(cacheStoreFactory);

        ccfg.setReadThrough(true);
        ccfg.setWriteThrough(true);

        ArrayList<QueryEntity> qryEntities = new ArrayList<>();

        QueryEntity qryEntity = new QueryEntity();

        qryEntity.setKeyType("java.lang.String");
        qryEntity.setValueType("com.eshipenet.shipnet.ship.Ship");
        qryEntity.setKeyFieldName("id");

        HashSet<String> keyFields = new HashSet<>();

        keyFields.add("id");

        qryEntity.setKeyFields(keyFields);

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();

        fields.put("mmsi", "java.lang.String");
        fields.put("name", "java.lang.String");
        fields.put("description", "java.lang.String");
        fields.put("avatar", "java.lang.String");
        fields.put("info", "java.lang.String");
        fields.put("ownerId", "java.lang.String");
        fields.put("createdAt", "java.sql.Timestamp");
        fields.put("updatedAt", "java.sql.Timestamp");
        fields.put("deletedAt", "java.sql.Timestamp");
        fields.put("id", "java.lang.String");

        qryEntity.setFields(fields);

        HashMap<String, String> aliases = new HashMap<>();

        aliases.put("ownerId", "owner_id");
        aliases.put("createdAt", "created_at");
        aliases.put("updatedAt", "updated_at");
        aliases.put("deletedAt", "deleted_at");

        qryEntity.setAliases(aliases);

        ArrayList<QueryIndex> indexes = new ArrayList<>();

        QueryIndex index = new QueryIndex();

        index.setName("mmsi");
        index.setIndexType(QueryIndexType.SORTED);

        LinkedHashMap<String, Boolean> indFlds = new LinkedHashMap<>();

        indFlds.put("mmsi", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("name");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("name", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("created_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("createdAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("deleted_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("deletedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("owner_id");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("ownerId", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("updated_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("updatedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        qryEntity.setIndexes(indexes);
        qryEntities.add(qryEntity);

        ccfg.setQueryEntities(qryEntities);

        return ccfg;
    }

    /**
     * Create JDBC type for "jdbcTypeShip".
     * 
     * @param cacheName Cache name.
     * @return Configured JDBC type.
     **/
    private static JdbcType jdbcTypeShip(String cacheName) {
        JdbcType type = new JdbcType();

        type.setCacheName(cacheName);
        type.setKeyType(String.class);
        type.setValueType("com.eshipenet.shipnet.ship.Ship");
        type.setDatabaseSchema("shipnettestv3");
        type.setDatabaseTable("ship");

        type.setKeyFields(new JdbcTypeField(Types.VARCHAR, "id", String.class, "id"));

        type.setValueFields(
            new JdbcTypeField(Types.VARCHAR, "mmsi", String.class, "mmsi"),
            new JdbcTypeField(Types.VARCHAR, "name", String.class, "name"),
            new JdbcTypeField(Types.LONGVARCHAR, "description", String.class, "description"),
            new JdbcTypeField(Types.VARCHAR, "avatar", String.class, "avatar"),
            new JdbcTypeField(Types.CHAR, "info", String.class, "info"),
            new JdbcTypeField(Types.VARCHAR, "owner_id", String.class, "ownerId"),
            new JdbcTypeField(Types.TIMESTAMP, "created_at", Timestamp.class, "createdAt"),
            new JdbcTypeField(Types.TIMESTAMP, "updated_at", Timestamp.class, "updatedAt"),
            new JdbcTypeField(Types.TIMESTAMP, "deleted_at", Timestamp.class, "deletedAt"),
            new JdbcTypeField(Types.VARCHAR, "id", String.class, "id")
        );

        return type;
    }

    /**
     * Create configuration for cache "ShipGovernorCache".
     * 
     * @return Configured cache.
     * @throws Exception if failed to create cache configuration.
     **/
    public static CacheConfiguration cacheShipGovernorCache() throws Exception {
        CacheConfiguration ccfg = new CacheConfiguration();

        ccfg.setName("ShipGovernorCache");
        ccfg.setCacheMode(CacheMode.PARTITIONED);
        ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);

        CacheJdbcPojoStoreFactory cacheStoreFactory = new CacheJdbcPojoStoreFactory();

        cacheStoreFactory.setDataSourceFactory(new Factory<DataSource>() {
            /** {@inheritDoc} **/
            @Override public DataSource create() {
                return DataSources.INSTANCE_dsMySQL_Shipnettestv3;
            };
        });

        cacheStoreFactory.setDialect(new MySQLDialect());

        cacheStoreFactory.setTypes(jdbcTypeShipGovernor(ccfg.getName()));

        ccfg.setCacheStoreFactory(cacheStoreFactory);

        ccfg.setReadThrough(true);
        ccfg.setWriteThrough(true);

        ArrayList<QueryEntity> qryEntities = new ArrayList<>();

        QueryEntity qryEntity = new QueryEntity();

        qryEntity.setKeyType("java.lang.String");
        qryEntity.setValueType("com.eshipenet.shipnet.ship.ShipGovernor");
        qryEntity.setTableName("ship_governor");
        qryEntity.setKeyFieldName("id");

        HashSet<String> keyFields = new HashSet<>();

        keyFields.add("id");

        qryEntity.setKeyFields(keyFields);

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();

        fields.put("name", "java.lang.String");
        fields.put("description", "java.lang.String");
        fields.put("avatar", "java.lang.String");
        fields.put("info", "java.lang.String");
        fields.put("createdAt", "java.sql.Timestamp");
        fields.put("updatedAt", "java.sql.Timestamp");
        fields.put("deletedAt", "java.sql.Timestamp");
        fields.put("id", "java.lang.String");

        qryEntity.setFields(fields);

        HashMap<String, String> aliases = new HashMap<>();

        aliases.put("createdAt", "created_at");
        aliases.put("updatedAt", "updated_at");
        aliases.put("deletedAt", "deleted_at");

        qryEntity.setAliases(aliases);

        ArrayList<QueryIndex> indexes = new ArrayList<>();

        QueryIndex index = new QueryIndex();

        index.setName("name");
        index.setIndexType(QueryIndexType.SORTED);

        LinkedHashMap<String, Boolean> indFlds = new LinkedHashMap<>();

        indFlds.put("name", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("created_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("createdAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("deleted_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("deletedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("updated_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("updatedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        qryEntity.setIndexes(indexes);
        qryEntities.add(qryEntity);

        ccfg.setQueryEntities(qryEntities);

        return ccfg;
    }

    /**
     * Create JDBC type for "jdbcTypeShipGovernor".
     * 
     * @param cacheName Cache name.
     * @return Configured JDBC type.
     **/
    private static JdbcType jdbcTypeShipGovernor(String cacheName) {
        JdbcType type = new JdbcType();

        type.setCacheName(cacheName);
        type.setKeyType(String.class);
        type.setValueType("com.eshipenet.shipnet.ship.ShipGovernor");
        type.setDatabaseSchema("shipnettestv3");
        type.setDatabaseTable("ship_governor");

        type.setKeyFields(new JdbcTypeField(Types.VARCHAR, "id", String.class, "id"));

        type.setValueFields(
            new JdbcTypeField(Types.VARCHAR, "name", String.class, "name"),
            new JdbcTypeField(Types.LONGVARCHAR, "description", String.class, "description"),
            new JdbcTypeField(Types.VARCHAR, "avatar", String.class, "avatar"),
            new JdbcTypeField(Types.CHAR, "info", String.class, "info"),
            new JdbcTypeField(Types.TIMESTAMP, "created_at", Timestamp.class, "createdAt"),
            new JdbcTypeField(Types.TIMESTAMP, "updated_at", Timestamp.class, "updatedAt"),
            new JdbcTypeField(Types.TIMESTAMP, "deleted_at", Timestamp.class, "deletedAt"),
            new JdbcTypeField(Types.VARCHAR, "id", String.class, "id")
        );

        return type;
    }

    /**
     * Create configuration for cache "ShipGovernorLinkCache".
     * 
     * @return Configured cache.
     * @throws Exception if failed to create cache configuration.
     **/
    public static CacheConfiguration cacheShipGovernorLinkCache() throws Exception {
        CacheConfiguration ccfg = new CacheConfiguration();

        ccfg.setName("ShipGovernorLinkCache");
        ccfg.setCacheMode(CacheMode.PARTITIONED);
        ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);

        CacheJdbcPojoStoreFactory cacheStoreFactory = new CacheJdbcPojoStoreFactory();

        cacheStoreFactory.setDataSourceFactory(new Factory<DataSource>() {
            /** {@inheritDoc} **/
            @Override public DataSource create() {
                return DataSources.INSTANCE_dsMySQL_Shipnettestv3;
            };
        });

        cacheStoreFactory.setDialect(new MySQLDialect());

        cacheStoreFactory.setTypes(jdbcTypeShipGovernorLink(ccfg.getName()));

        ccfg.setCacheStoreFactory(cacheStoreFactory);

        ccfg.setReadThrough(true);
        ccfg.setWriteThrough(true);

        ArrayList<QueryEntity> qryEntities = new ArrayList<>();

        QueryEntity qryEntity = new QueryEntity();

        qryEntity.setKeyType("com.eshipenet.shipnet.ship.ShipGovernorLinkKey");
        qryEntity.setValueType("com.eshipenet.shipnet.ship.ShipGovernorLink");
        qryEntity.setTableName("ship_governor_link");

        HashSet<String> keyFields = new HashSet<>();

        keyFields.add("shipId");

        keyFields.add("shipGovernorId");

        qryEntity.setKeyFields(keyFields);

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();

        fields.put("shipId", "java.lang.String");
        fields.put("shipGovernorId", "java.lang.String");
        fields.put("createdAt", "java.sql.Timestamp");
        fields.put("updatedAt", "java.sql.Timestamp");

        qryEntity.setFields(fields);

        HashMap<String, String> aliases = new HashMap<>();

        aliases.put("shipId", "ship_id");
        aliases.put("shipGovernorId", "ship_governor_id");
        aliases.put("createdAt", "created_at");
        aliases.put("updatedAt", "updated_at");

        qryEntity.setAliases(aliases);
        qryEntities.add(qryEntity);

        ccfg.setQueryEntities(qryEntities);

        return ccfg;
    }

    /**
     * Create JDBC type for "jdbcTypeShipGovernorLink".
     * 
     * @param cacheName Cache name.
     * @return Configured JDBC type.
     **/
    private static JdbcType jdbcTypeShipGovernorLink(String cacheName) {
        JdbcType type = new JdbcType();

        type.setCacheName(cacheName);
        type.setKeyType("com.eshipenet.shipnet.ship.ShipGovernorLinkKey");
        type.setValueType("com.eshipenet.shipnet.ship.ShipGovernorLink");
        type.setDatabaseSchema("shipnettestv3");
        type.setDatabaseTable("ship_governor_link");

        type.setKeyFields(
            new JdbcTypeField(Types.VARCHAR, "ship_id", String.class, "shipId"),
            new JdbcTypeField(Types.VARCHAR, "ship_governor_id", String.class, "shipGovernorId")
        );

        type.setValueFields(
            new JdbcTypeField(Types.TIMESTAMP, "created_at", Timestamp.class, "createdAt"),
            new JdbcTypeField(Types.TIMESTAMP, "updated_at", Timestamp.class, "updatedAt"),
            new JdbcTypeField(Types.VARCHAR, "ship_id", String.class, "shipId"),
            new JdbcTypeField(Types.VARCHAR, "ship_governor_id", String.class, "shipGovernorId")
        );

        return type;
    }

    /**
     * Create configuration for cache "ShipOwnerCache".
     * 
     * @return Configured cache.
     * @throws Exception if failed to create cache configuration.
     **/
    public static CacheConfiguration cacheShipOwnerCache() throws Exception {
        CacheConfiguration ccfg = new CacheConfiguration();

        ccfg.setName("ShipOwnerCache");
        ccfg.setCacheMode(CacheMode.PARTITIONED);
        ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);

        CacheJdbcPojoStoreFactory cacheStoreFactory = new CacheJdbcPojoStoreFactory();

        cacheStoreFactory.setDataSourceFactory(new Factory<DataSource>() {
            /** {@inheritDoc} **/
            @Override public DataSource create() {
                return DataSources.INSTANCE_dsMySQL_Shipnettestv3;
            };
        });

        cacheStoreFactory.setDialect(new MySQLDialect());

        cacheStoreFactory.setTypes(jdbcTypeShipOwner(ccfg.getName()));

        ccfg.setCacheStoreFactory(cacheStoreFactory);

        ccfg.setReadThrough(true);
        ccfg.setWriteThrough(true);

        ArrayList<QueryEntity> qryEntities = new ArrayList<>();

        QueryEntity qryEntity = new QueryEntity();

        qryEntity.setKeyType("java.lang.String");
        qryEntity.setValueType("com.eshipenet.shipnet.ship.ShipOwner");
        qryEntity.setTableName("ship_owner");
        qryEntity.setKeyFieldName("id");

        HashSet<String> keyFields = new HashSet<>();

        keyFields.add("id");

        qryEntity.setKeyFields(keyFields);

        LinkedHashMap<String, String> fields = new LinkedHashMap<>();

        fields.put("name", "java.lang.String");
        fields.put("description", "java.lang.String");
        fields.put("avatar", "java.lang.String");
        fields.put("info", "java.lang.String");
        fields.put("createdAt", "java.sql.Timestamp");
        fields.put("updatedAt", "java.sql.Timestamp");
        fields.put("deletedAt", "java.sql.Timestamp");
        fields.put("id", "java.lang.String");

        qryEntity.setFields(fields);

        HashMap<String, String> aliases = new HashMap<>();

        aliases.put("createdAt", "created_at");
        aliases.put("updatedAt", "updated_at");
        aliases.put("deletedAt", "deleted_at");

        qryEntity.setAliases(aliases);

        ArrayList<QueryIndex> indexes = new ArrayList<>();

        QueryIndex index = new QueryIndex();

        index.setName("name");
        index.setIndexType(QueryIndexType.SORTED);

        LinkedHashMap<String, Boolean> indFlds = new LinkedHashMap<>();

        indFlds.put("name", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("created_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("createdAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("deleted_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("deletedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        index = new QueryIndex();

        index.setName("updated_at");
        index.setIndexType(QueryIndexType.SORTED);

        indFlds = new LinkedHashMap<>();

        indFlds.put("updatedAt", false);

        index.setFields(indFlds);
        indexes.add(index);

        qryEntity.setIndexes(indexes);
        qryEntities.add(qryEntity);

        ccfg.setQueryEntities(qryEntities);

        return ccfg;
    }

    /**
     * Create JDBC type for "jdbcTypeShipOwner".
     * 
     * @param cacheName Cache name.
     * @return Configured JDBC type.
     **/
    private static JdbcType jdbcTypeShipOwner(String cacheName) {
        JdbcType type = new JdbcType();

        type.setCacheName(cacheName);
        type.setKeyType(String.class);
        type.setValueType("com.eshipenet.shipnet.ship.ShipOwner");
        type.setDatabaseSchema("shipnettestv3");
        type.setDatabaseTable("ship_owner");

        type.setKeyFields(new JdbcTypeField(Types.VARCHAR, "id", String.class, "id"));

        type.setValueFields(
            new JdbcTypeField(Types.VARCHAR, "name", String.class, "name"),
            new JdbcTypeField(Types.LONGVARCHAR, "description", String.class, "description"),
            new JdbcTypeField(Types.VARCHAR, "avatar", String.class, "avatar"),
            new JdbcTypeField(Types.CHAR, "info", String.class, "info"),
            new JdbcTypeField(Types.TIMESTAMP, "created_at", Timestamp.class, "createdAt"),
            new JdbcTypeField(Types.TIMESTAMP, "updated_at", Timestamp.class, "updatedAt"),
            new JdbcTypeField(Types.TIMESTAMP, "deleted_at", Timestamp.class, "deletedAt"),
            new JdbcTypeField(Types.VARCHAR, "id", String.class, "id")
        );

        return type;
    }
}